home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / m4-1_0_3.lha / m4-1.0.3 / builtin.c < prev    next >
C/C++ Source or Header  |  1992-12-19  |  38KB  |  1,651 lines

  1. /*
  2.  * GNU m4 -- A simple macro processor
  3.  * Copyright (C) 1989-1992 Free Software Foundation, Inc.
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2, or (at your option)
  8.  * any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20. /*
  21.  * Code for all builtin macros, initialisation of symbol table, and
  22.  * expansion of user defined macros.
  23.  */
  24.  
  25. #include "m4.h"
  26. #ifndef size_t
  27. #include <sys/types.h>
  28. #endif
  29. #include "regex.h"
  30.  
  31. #define ARG(i)    (argc > (i) ? TOKEN_DATA_TEXT (argv[i]) : "")
  32.  
  33.  
  34. /*
  35.  * Initialisation of builtin and predefined macros.  The table
  36.  * "builtin_tab" is both used for initialisation, and by the "builtin"
  37.  * builtin.
  38.  */
  39. #ifndef __STDC__
  40. #define DECLARE(name) static void name ()
  41. #else
  42. #define DECLARE(name) static void name (struct obstack *, int, token_data **)
  43. #endif
  44.  
  45. DECLARE (m4___file__);
  46. DECLARE (m4___line__);
  47. DECLARE (m4_builtin);
  48. DECLARE (m4_changecom);
  49. DECLARE (m4_changequote);
  50. DECLARE (m4_debugmode);
  51. DECLARE (m4_debugfile);
  52. DECLARE (m4_decr);
  53. DECLARE (m4_define);
  54. DECLARE (m4_defn);
  55. DECLARE (m4_divert);
  56. DECLARE (m4_divnum);
  57. DECLARE (m4_dnl);
  58. DECLARE (m4_dumpdef);
  59. DECLARE (m4_errprint);
  60. DECLARE (m4_esyscmd);
  61. DECLARE (m4_eval);
  62. DECLARE (m4_format);
  63. DECLARE (m4_ifdef);
  64. DECLARE (m4_ifelse);
  65. DECLARE (m4_include);
  66. DECLARE (m4_incr);
  67. DECLARE (m4_index);
  68. DECLARE (m4_indir);
  69. DECLARE (m4_len);
  70. DECLARE (m4_m4exit);
  71. DECLARE (m4_m4wrap);
  72. DECLARE (m4_maketemp);
  73. DECLARE (m4_patsubst);
  74. DECLARE (m4_popdef);
  75. DECLARE (m4_pushdef);
  76. DECLARE (m4_regexp);
  77. DECLARE (m4_shift);
  78. DECLARE (m4_sinclude);
  79. DECLARE (m4_substr);
  80. DECLARE (m4_syscmd);
  81. DECLARE (m4_sysval);
  82. DECLARE (m4_traceoff);
  83. DECLARE (m4_traceon);
  84. DECLARE (m4_translit);
  85. DECLARE (m4_undefine);
  86. DECLARE (m4_undivert);
  87.  
  88. #undef DECLARE
  89.  
  90. static builtin const
  91. builtin_tab[] =
  92. {
  93.  
  94.   /* name        gnu    args    function */
  95.  
  96.   { "__file__",        TRUE,    FALSE,    m4___file__ },
  97.   { "__line__",        TRUE,    FALSE,    m4___line__ },
  98.   { "builtin",        TRUE,    FALSE,    m4_builtin },
  99.   { "changecom",    FALSE,    FALSE,    m4_changecom },
  100.   { "changequote",    FALSE,    FALSE,    m4_changequote },
  101.   { "debugmode",    TRUE,    FALSE,    m4_debugmode },
  102.   { "debugfile",    TRUE,    FALSE,    m4_debugfile },
  103.   { "decr",        FALSE,    FALSE,    m4_decr },
  104.   { "define",        FALSE,    TRUE,    m4_define },
  105.   { "defn",        FALSE,    FALSE,    m4_defn },
  106.   { "divert",        FALSE,    FALSE,    m4_divert },
  107.   { "divnum",        FALSE,    FALSE,    m4_divnum },
  108.   { "dnl",        FALSE,    FALSE,    m4_dnl },
  109.   { "dumpdef",        FALSE,    FALSE,    m4_dumpdef },
  110.   { "errprint",        FALSE,    FALSE,    m4_errprint },
  111.   { "esyscmd",        TRUE,    FALSE,    m4_esyscmd },
  112.   { "eval",        FALSE,    FALSE,    m4_eval },
  113.   { "format",        TRUE,    FALSE,    m4_format },
  114.   { "ifdef",        FALSE,    FALSE,    m4_ifdef },
  115.   { "ifelse",        FALSE,    FALSE,    m4_ifelse },
  116.   { "include",        FALSE,    FALSE,    m4_include },
  117.   { "incr",        FALSE,    FALSE,    m4_incr },
  118.   { "index",        FALSE,    FALSE,    m4_index },
  119.   { "indir",        TRUE,    FALSE,    m4_indir },
  120.   { "len",        FALSE,    FALSE,    m4_len },
  121.   { "m4exit",        FALSE,    FALSE,    m4_m4exit },
  122.   { "m4wrap",        FALSE,    FALSE,    m4_m4wrap },
  123.   { "maketemp",        FALSE,    FALSE,    m4_maketemp },
  124.   { "patsubst",        TRUE,    FALSE,    m4_patsubst },
  125.   { "popdef",        FALSE,    FALSE,    m4_popdef },
  126.   { "pushdef",        FALSE,    TRUE,    m4_pushdef },
  127.   { "regexp",        TRUE,    FALSE,    m4_regexp },
  128.   { "shift",        FALSE,    FALSE,    m4_shift },
  129.   { "sinclude",        FALSE,    FALSE,    m4_sinclude },
  130.   { "substr",        FALSE,    FALSE,    m4_substr },
  131.   { "syscmd",        FALSE,    FALSE,    m4_syscmd },
  132.   { "sysval",        FALSE,    FALSE,    m4_sysval },
  133.   { "traceoff",        FALSE,    FALSE,    m4_traceoff },
  134.   { "traceon",        FALSE,    FALSE,    m4_traceon },
  135.   { "translit",        FALSE,    FALSE,    m4_translit },
  136.   { "undefine",        FALSE,    FALSE,    m4_undefine },
  137.   { "undivert",        FALSE,    FALSE,    m4_undivert },
  138.  
  139.   { 0,            FALSE,    FALSE,    0 },
  140. };
  141.  
  142. static predefined const
  143. predefined_tab[] =
  144. {
  145.   { "unix",    "__unix__",    "" },
  146.   { NULL,    "__gnu__",    "" },
  147.  
  148.   { NULL,    NULL,        NULL },
  149. };
  150.  
  151. /* The number of the currently active diversion.  */
  152. static int current_diversion;
  153.  
  154.  
  155. /*
  156.  * Find the builtin, which lives on ADDR
  157.  */
  158.  
  159. const builtin *
  160. find_builtin_by_addr (builtin_func *func)
  161. {
  162.   const builtin *bp;
  163.  
  164.   for (bp = &builtin_tab[0]; bp->name != NULL; bp++)
  165.     if (bp->func == func)
  166.       return bp;
  167.   return NULL;
  168. }
  169.  
  170. /*
  171.  * Find the builtin, which has NAME
  172.  */
  173.  
  174. const builtin *
  175. find_builtin_by_name (char *name)
  176. {
  177.   const builtin *bp;
  178.  
  179.   for (bp = &builtin_tab[0]; bp->name != NULL; bp++)
  180.     if (strcmp (bp->name, name) == 0)
  181.       return bp;
  182.   return NULL;
  183. }
  184.  
  185.  
  186. /*
  187.  * Install a builtin macro with name NAME, bound to the C function given
  188.  * in BP.  MODE is SYMBOL_INSERT or SYMBOL_PUSHDEF.  TRACED defines
  189.  * wheather NAME is to be traced.
  190.  */
  191. static void
  192. define_builtin (const char *name, const builtin *bp, symbol_lookup mode,
  193.         boolean traced)
  194. {
  195.   symbol *sym;
  196.  
  197.   sym = lookup_symbol (name, mode);
  198.   SYMBOL_TYPE (sym) = TOKEN_FUNC;
  199.   SYMBOL_MACRO_ARGS (sym) = bp->groks_macro_args;
  200.   SYMBOL_FUNC (sym) = bp->func;
  201.   SYMBOL_TRACED (sym) = traced;
  202. }
  203.  
  204. /*
  205.  * Define a predefined or user-defined macro, with name NAME, and
  206.  * expansion TEXT.  MODE destinguishes between the "define" and the
  207.  * "pushdef" case.  It is also used from main ().
  208.  */
  209. void
  210. define_user_macro (const char *name, const char *text, symbol_lookup mode)
  211. {
  212.   symbol *s;
  213.  
  214.   s = lookup_symbol (name, mode);
  215.   if (SYMBOL_TYPE (s) == TOKEN_TEXT)
  216.     xfree (SYMBOL_TEXT (s));
  217.  
  218.   SYMBOL_TYPE (s) = TOKEN_TEXT;
  219.   SYMBOL_TEXT (s) = xstrdup (text);
  220. }
  221.  
  222. /*
  223.  * Initialise all builtin and predefined macros.
  224.  */
  225. void
  226. builtin_init (void)
  227. {
  228.   const builtin *bp;
  229.   const predefined *pp;
  230.  
  231.   for (bp = &builtin_tab[0]; bp->name != NULL; bp++)
  232.     {
  233.       if (!(no_gnu_extensions && bp->gnu_extension))
  234.     define_builtin (bp->name, bp, SYMBOL_INSERT, FALSE);
  235.     }
  236.  
  237.   for (pp = &predefined_tab[0]; pp->func != NULL; pp++)
  238.     {
  239.       if (no_gnu_extensions)
  240.     {
  241.       if (pp->unix_name != NULL)
  242.         define_user_macro (pp->unix_name, pp->func, SYMBOL_INSERT);
  243.     }
  244.       else
  245.     {
  246.       if (pp->gnu_name != NULL)
  247.         define_user_macro (pp->gnu_name, pp->func, SYMBOL_INSERT);
  248.     }
  249.     }
  250.  
  251.   current_diversion = 0;
  252. }
  253.  
  254. /*
  255.  * Give friendly warnings if a builtin macro is passed an inappropriate
  256.  * number of arguments.  NAME is macro name for messages, ARGC is actual
  257.  * number of arguments, MIN is minimum number of acceptable arguments,
  258.  * negative if applicable, MAX is maximum number, negative if in not
  259.  * applicable.
  260.  */
  261. static boolean
  262. bad_argc (token_data *name, int argc, int min, int max)
  263. {
  264.   boolean isbad = FALSE;
  265.  
  266.   if (min > 0 && argc < min)
  267.     {
  268.       if (!suppress_warnings)
  269.     warning ("too few arguments to built-in `%s'", TOKEN_DATA_TEXT (name));
  270.       isbad = TRUE;
  271.     }
  272.   else if (max > 0 && argc > max && !suppress_warnings)
  273.     warning ("excess arguments to built-in `%s' ignored",
  274.          TOKEN_DATA_TEXT (name));
  275.  
  276.   return isbad;
  277. }
  278.  
  279. /*
  280.  * The function numeric_arg () converts ARG to an int pointed to by
  281.  * VALUEP.  If the conversion fails, print error message for macro
  282.  * MACRO.   Return TRUE iff conversion succeeds.
  283.  */
  284. static boolean
  285. numeric_arg (token_data *macro, char *arg, int *valuep)
  286. {
  287.   if (sscanf (arg, "%d", valuep) != 1)
  288.     {
  289.       error ("non-numeric argument to built-in `%s'", TOKEN_DATA_TEXT (macro));
  290.       return FALSE;
  291.     }
  292.   return TRUE;
  293. }
  294.  
  295. /*
  296.  * The function ntoa () converts VALUE to a signed ascii representation in
  297.  * radix RADIX.
  298.  */
  299.  
  300. /* Digits for number to ascii conversions.  */
  301. static char const digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
  302.  
  303. static char *
  304. ntoa (register int value, int radix)
  305. {
  306.   boolean negative;
  307.   unsigned int uvalue;
  308.   static char str[256];
  309.   register char *s = &str[sizeof str];
  310.  
  311.   *--s = '\0';
  312.  
  313.   if (value < 0)
  314.     {
  315.       negative = TRUE;
  316.       uvalue = (unsigned int) -value;
  317.     }
  318.   else
  319.     {
  320.       negative = FALSE;
  321.       uvalue = (unsigned int) value;
  322.     }
  323.  
  324.   do
  325.     {
  326.       *--s = digits[uvalue % radix];
  327.       uvalue /= radix;
  328.     }
  329.   while (uvalue > 0);
  330.  
  331.   if (negative)
  332.     *--s = '-';
  333.   return s;
  334. }
  335.  
  336. /*
  337.  * Format an int VAL, and stuff it into an obstack OBS.  Used for macros
  338.  * expanding to numbers.
  339.  */
  340. static void
  341. shipout_int (struct obstack *obs, int val)
  342. {
  343.   char *s;
  344.  
  345.   s = ntoa (val, 10);
  346.   obstack_grow (obs, s, strlen (s));
  347. }
  348.  
  349.  
  350. /*
  351.  * Print ARGC arguments from the table ARGV to obstack OBS, separated by
  352.  * SEP, and quoted by the current quotes, if QUOTED is TRUE.
  353.  */
  354. static void
  355. dump_args (struct obstack *obs, int argc, token_data **argv,
  356.        char *sep, boolean quoted)
  357. {
  358.   int i;
  359.   int len = strlen (sep);
  360.  
  361.   for (i = 1; i < argc; i++)
  362.     {
  363.       if (i > 1)
  364.     obstack_grow (obs, sep, len);
  365.       if (quoted)
  366.     obstack_grow (obs, lquote, len_lquote);
  367.       obstack_grow (obs, TOKEN_DATA_TEXT (argv[i]),
  368.             strlen (TOKEN_DATA_TEXT (argv[i])));
  369.       if (quoted)
  370.     obstack_grow (obs, rquote, len_rquote);
  371.     }
  372.  
  373. }
  374.  
  375.  
  376. /*
  377.  * The rest of this file is code for builtins and expansion of user
  378.  * defined macros.  All the functions for builtins have a prototype as:
  379.  *
  380.  *     void m4_MACRONAME (struct obstack *obs, int argc, char *argv[]);
  381.  *
  382.  * The function are expected to leave their expansion on the obstack
  383.  * OBS, as an unfinished object.  ARGV is a table of ARGC pointers to
  384.  * the individual arguments to the macro.  Please note that in general
  385.  * argv[argc] != NULL.
  386.  */
  387.  
  388. /*
  389.  * The first section are macros for definining, undefining, examining,
  390.  * changing, ... other macros.
  391.  */
  392.  
  393. /*
  394.  * The function define_macro is common for the builtins "define",
  395.  * "undefine", "pushdef" and "popdef".  ARGC and ARGV is as for the
  396.  * caller, and MODE argument determines how the macro name is entered
  397.  * into the symbol table.
  398.  */
  399. static void
  400. define_macro (int argc, token_data **argv, symbol_lookup mode)
  401. {
  402.   const builtin *bp;
  403.  
  404.   if (bad_argc (argv[0], argc, 3, 3))
  405.     return;
  406.  
  407.   if (TOKEN_DATA_TYPE (argv[1]) != TOKEN_TEXT)
  408.     return;
  409.  
  410.   switch (TOKEN_DATA_TYPE (argv[2]))
  411.     {
  412.     case TOKEN_TEXT:
  413.       define_user_macro (ARG (1), ARG (2), mode);
  414.       break;
  415.     case TOKEN_FUNC:
  416.       bp = find_builtin_by_addr (TOKEN_DATA_FUNC (argv[2]));
  417.       if (bp == NULL)
  418.     return;
  419.       else
  420.     define_builtin (ARG (1), bp, mode, TOKEN_DATA_FUNC_TRACED (argv[2]));
  421.       break;
  422.     default:
  423.       internal_error ("Bad token data type in define_macro ()");
  424.       break;
  425.     }
  426.   return;
  427. }
  428.  
  429. static void
  430. m4_define (struct obstack *obs, int argc, token_data **argv)
  431. {
  432.   define_macro (argc, argv, SYMBOL_INSERT);
  433. }
  434.  
  435.  
  436. static void
  437. m4_undefine (struct obstack *obs, int argc, token_data **argv)
  438. {
  439.   if (bad_argc (argv[0], argc, 2, 2))
  440.     return;
  441.   lookup_symbol (ARG (1), SYMBOL_DELETE);
  442. }
  443.  
  444. static void
  445. m4_pushdef (struct obstack *obs, int argc, token_data **argv)
  446. {
  447.   define_macro (argc, argv,  SYMBOL_PUSHDEF);
  448. }
  449.  
  450.  
  451. static void
  452. m4_popdef (struct obstack *obs, int argc, token_data **argv)
  453. {
  454.   if (bad_argc (argv[0], argc, 2, 2))
  455.     return;
  456.   lookup_symbol (ARG (1), SYMBOL_POPDEF);
  457. }
  458.  
  459.  
  460. /*
  461.  * Conditionals of m4.
  462.  */
  463. static void
  464. m4_ifdef (struct obstack *obs, int argc, token_data **argv)
  465. {
  466.   symbol *s;
  467.   char *result;
  468.  
  469.   if (bad_argc (argv[0], argc, 3, 4))
  470.     return;
  471.   s = lookup_symbol (ARG (1), SYMBOL_LOOKUP);
  472.  
  473.   if (s != NULL)
  474.     result = ARG (2);
  475.   else if (argc == 4)
  476.     result = ARG (3);
  477.   else
  478.     result = NULL;
  479.  
  480.   if (result != NULL)
  481.     obstack_grow (obs, result, strlen (result));
  482. }
  483.  
  484. static void
  485. m4_ifelse (struct obstack *obs, int argc, token_data **argv)
  486. {
  487.   char *result;
  488.   token_data *argv0;
  489.  
  490.   if (argc == 2)
  491.     return;
  492.  
  493.   argv0 = argv[0];
  494.   argv++;
  495.   argc--;
  496.  
  497.   result = NULL;
  498.   while (result == NULL)
  499.     {
  500.       if (bad_argc (argv0, argc, 3, -1))
  501.     return;
  502.  
  503.       if (strcmp (ARG (0), ARG (1)) == 0)
  504.     result = ARG (2);
  505.       else
  506.     switch (argc)
  507.       {
  508.       case 3:
  509.         return;
  510.       case 4:
  511.         result = ARG (3);
  512.         break;
  513.       default:
  514.         argc -= 3;
  515.         argv += 3;
  516.       }
  517.     }
  518.   obstack_grow (obs, result, strlen (result));
  519. }
  520.  
  521.  
  522. /*
  523.  * The function dump_symbol () is for use by "dumpdef".  It builds up a
  524.  * table of all defined, un-shadowed, symbols.  The structure
  525.  * dump_symbol_data is used to pass the information needed from call to
  526.  * call to dump_symbol.
  527.  */
  528.  
  529. struct dump_symbol_data
  530. {
  531.   struct obstack *obs;        /* obstack for table */
  532.   symbol **base;        /* base of table */
  533.   int size;            /* size of table */
  534. };
  535.  
  536. static void
  537. dump_symbol (symbol *sym, struct dump_symbol_data *data)
  538. {
  539.   if (!SYMBOL_SHADOWED (sym) && SYMBOL_TYPE (sym) != TOKEN_VOID)
  540.     {
  541.       obstack_blank (data->obs, sizeof (symbol *));
  542.       data->base = (symbol **) obstack_base (data->obs);
  543.       data->base[data->size++] = sym;
  544.     }
  545. }
  546.  
  547. /*
  548.  * qsort comparison routine, for sorting the table made in m4_dumpdef ().
  549.  */
  550. static int
  551. dumpdef_cmp (const void *s1, const void *s2)
  552. {
  553.   return strcmp (SYMBOL_NAME (* (const symbol **) s1),
  554.          SYMBOL_NAME (* (const symbol **) s2));
  555. }
  556.  
  557. /*
  558.  * Implementation of "dumpdef" itself.  It builds up a table of pointers
  559.  * to symbols, sorts it and prints the sorted table.
  560.  */
  561. static void
  562. m4_dumpdef (struct obstack *obs, int argc, token_data **argv)
  563. {
  564.   symbol *s;
  565.   int i;
  566.   struct dump_symbol_data data;
  567.   const builtin *bp;
  568.  
  569.   data.obs = obs;
  570.   data.base = (symbol **) obstack_base (obs);
  571.   data.size = 0;
  572.  
  573.   if (argc == 1)
  574.     {
  575.       hack_all_symbols (dump_symbol, (char *) &data);
  576.     }
  577.   else
  578.     {
  579.       for (i = 1; i < argc; i++)
  580.     {
  581.       s = lookup_symbol (TOKEN_DATA_TEXT (argv[i]), SYMBOL_LOOKUP);
  582.       if (s != NULL && SYMBOL_TYPE (s) != TOKEN_VOID)
  583.         dump_symbol (s, &data);
  584.       else
  585.         error ("Undefined name %s", TOKEN_DATA_TEXT (argv[i]));
  586.     }
  587.     }
  588.   /* make table of symbols invisible to expand_macro () */
  589.   (void) obstack_finish (obs);
  590.  
  591.   qsort ((char *) data.base, data.size, sizeof (symbol *), dumpdef_cmp);
  592.  
  593.   for (; data.size > 0; --data.size, data.base++)
  594.     {
  595.       debug_print ("%s:\t", SYMBOL_NAME (data.base[0]));
  596.  
  597.       switch (SYMBOL_TYPE (data.base[0]))
  598.     {
  599.     case TOKEN_TEXT:
  600.       if (debug_level & DEBUG_TRACE_QUOTE)
  601.         debug_print ("%s%s%s\n", lquote, SYMBOL_TEXT (data.base[0]), rquote);
  602.       else
  603.         debug_print ("%s\n", SYMBOL_TEXT (data.base[0]));
  604.       break;
  605.     case TOKEN_FUNC:
  606.       bp = find_builtin_by_addr (SYMBOL_FUNC (data.base[0]));
  607.       if (bp == NULL)
  608.         internal_error ("built-in not found in builtin table!");
  609.       debug_print ("<%s>\n", bp->name);
  610.       break;
  611.     default:
  612.       internal_error ("Bad token data type in m4_dumpdef ()");
  613.       break;
  614.     }
  615.     }
  616. }
  617.  
  618. /*
  619.  * This is GNU specific.  The builtin "builtin" allows calls to builtin
  620.  * macros, even if their definition has been overridden or shadowed.  It
  621.  * is thus possible to redefine builtins, and still access their
  622.  * original definition.
  623.  *
  624.  * This macro is not available in compatibility mode.
  625.  */
  626. static void
  627. m4_builtin (struct obstack *obs, int argc, token_data **argv)
  628. {
  629.   const builtin *bp;
  630.   char *name = ARG (1);
  631.  
  632.   if (bad_argc (argv[0], argc, 2, -1))
  633.     return;
  634.  
  635.   bp = find_builtin_by_name (name);
  636.   if (bp == NULL)
  637.     error ("Undefined name %s", name);
  638.   else
  639.     (*bp->func) (obs, argc - 1, argv + 1);
  640. }
  641.  
  642. /*
  643.  * This is GNU specific.  The builtin "indir" allows indirect calls to
  644.  * macros, even if their name is not a proper macro name.  It
  645.  * is thus possible to define macros with ill-formed names for internal
  646.  * use in larger macro packages.
  647.  *
  648.  * This macro is not available in compatibility mode.
  649.  */
  650. static void
  651. m4_indir (struct obstack *obs, int argc, token_data **argv)
  652. {
  653.   symbol *s;
  654.   char *name = ARG (1);
  655.  
  656.   if (bad_argc (argv[0], argc, 1, -1))
  657.     return;
  658.  
  659.   s = lookup_symbol (name, SYMBOL_LOOKUP);
  660.   if (s == NULL)
  661.     error ("Undefined macro `%s'", name);
  662.   else
  663.     call_macro (s, argc - 1, argv + 1, obs);
  664. }
  665.  
  666. /*
  667.  * The macro "defn" returns the quoted definition of the macro named by
  668.  * the first argument.  If the macro is builtin, it will push a special
  669.  * macro-definition token on ht input stack.
  670.  */
  671. static void
  672. m4_defn (struct obstack *obs, int argc, token_data **argv)
  673. {
  674.   symbol *s;
  675.  
  676.   if (bad_argc (argv[0], argc, 2, 2))
  677.     return;
  678.  
  679.   s = lookup_symbol (ARG (1), SYMBOL_LOOKUP);
  680.   if (s == NULL)
  681.     return;
  682.  
  683.   switch (SYMBOL_TYPE (s))
  684.     {
  685.     case TOKEN_TEXT:
  686.       obstack_grow (obs, lquote, len_lquote);
  687.       obstack_grow (obs, SYMBOL_TEXT (s), strlen (SYMBOL_TEXT (s)));
  688.       obstack_grow (obs, rquote, len_rquote);
  689.       break;
  690.     case TOKEN_FUNC:
  691.       push_macro (SYMBOL_FUNC (s), SYMBOL_TRACED (s));
  692.       break;
  693.     case TOKEN_VOID:
  694.       break;
  695.     default:
  696.       internal_error ("Bad symbol type in m4_defn ()");
  697.       break;
  698.     }
  699. }
  700.  
  701.  
  702. /*
  703.  * This section contains macros to handle the builtins "syscmd",
  704.  * "esyscmd" and "sysval".  "esyscmd" is GNU specific.
  705.  */
  706.  
  707. /* Exit code from last "syscmd" command.  */
  708. static int sysval;
  709.  
  710. static void
  711. m4_syscmd (struct obstack *obs, int argc, token_data **argv)
  712. {
  713.   if (bad_argc (argv[0], argc, 2, 2))
  714.     return;
  715.   sysval = system (ARG (1));
  716. }
  717.  
  718. static void
  719. m4_esyscmd (struct obstack *obs, int argc, token_data **argv)
  720. {
  721.   FILE *pin;
  722.   int ch;
  723.  
  724.   if (bad_argc (argv[0], argc, 2, 2))
  725.     return;
  726.  
  727.   pin = popen (ARG (1), "r");
  728.   if (pin == NULL)
  729.     {
  730.       error ("Cannot open pipe to command \"%s\": %s", ARG (1), syserr ());
  731.       sysval = 0xff << 8;
  732.     }
  733.   else
  734.     {
  735.       while ((ch = getc (pin)) != EOF)
  736.     obstack_1grow (obs, (char) ch);
  737.       sysval = pclose (pin);
  738.     }
  739. }
  740.  
  741. static void
  742. m4_sysval (struct obstack *obs, int argc, token_data **argv)
  743. {
  744.   shipout_int (obs, (sysval >> 8) & 0xff);
  745. }
  746.  
  747.  
  748.  
  749. /*
  750.  * This section contains the top level code for the "eval" builtin.  The
  751.  * actual work is done in the function evaluate (), which lives in
  752.  * eval.c.
  753.  */
  754.  
  755. static void
  756. m4_eval (struct obstack *obs, int argc, token_data **argv)
  757. {
  758.   int value;
  759.   int radix = 10;
  760.   int min = 1;
  761.   char *s;
  762.  
  763.   if (bad_argc (argv[0], argc, 2, 4))
  764.     return;
  765.  
  766.   if (argc >= 3 && !numeric_arg (argv[0], ARG (2), &radix))
  767.     return;
  768.  
  769.   if (radix <= 1 || radix > strlen (digits))
  770.     {
  771.       error ("radix in eval out of range (radix = %d)", radix);
  772.       return;
  773.     }
  774.  
  775.   if (argc >= 4 && !numeric_arg (argv[0], ARG (3), &min))
  776.     return;
  777.   if  (min <= 0)
  778.     {
  779.       error ("negative width to eval");
  780.       return;
  781.     }
  782.  
  783.   if (evaluate (ARG (1), &value))
  784.     return;
  785.  
  786.   s = ntoa (value, radix);
  787.  
  788.   if (*s == '-')
  789.     {
  790.       obstack_1grow (obs, '-');
  791.       min--;
  792.       s++;
  793.     }
  794.   for (min -= strlen (s); --min >= 0;)
  795.     obstack_1grow (obs, '0');
  796.  
  797.   obstack_grow (obs, s, strlen (s));
  798. }
  799.  
  800. static void
  801. m4_incr (struct obstack *obs, int argc, token_data **argv)
  802. {
  803.   int value;
  804.  
  805.   if (bad_argc (argv[0], argc, 2, 2))
  806.     return;
  807.  
  808.   if (!numeric_arg (argv[0], ARG (1), &value))
  809.     return;
  810.  
  811.   shipout_int (obs, value + 1);
  812. }
  813.  
  814. static void
  815. m4_decr (struct obstack *obs, int argc, token_data **argv)
  816. {
  817.   int value;
  818.  
  819.   if (bad_argc (argv[0], argc, 2, 2))
  820.     return;
  821.  
  822.   if (!numeric_arg (argv[0], ARG (1), &value))
  823.     return;
  824.  
  825.   shipout_int (obs, value - 1);
  826. }
  827.  
  828.  
  829. /*
  830.  * This section contains the macros "divert", "undivert" and "divnum"
  831.  * for handling diversion.  The utility functions used lives in output.c
  832.  */
  833.  
  834. /*
  835.  * Divert further output to the diversion given by ARGV[1].  Out of
  836.  * range means discard further output.
  837.  */
  838. static void
  839. m4_divert (struct obstack *obs, int argc, token_data **argv)
  840. {
  841.   int i = 0;
  842.  
  843.   if (bad_argc (argv[0], argc, 1, 2))
  844.     return;
  845.  
  846.   if (argc == 2 && !numeric_arg (argv[0], ARG (1), &i))
  847.     return;
  848.  
  849.   make_diversion (i);
  850.   current_diversion = i;
  851. }
  852.  
  853. /*
  854.  * Expand to the current diversion number, -1 if none.
  855.  */
  856. static void
  857. m4_divnum (struct obstack *obs, int argc, token_data **argv)
  858. {
  859.   if (bad_argc (argv[0], argc, 1, 1))
  860.     return;
  861.   shipout_int (obs, current_diversion);
  862. }
  863.  
  864. /*
  865.  * Bring back the diversion given by the argument list.  If none is
  866.  * specified, bring back all diversions.  GNU specific is the option of
  867.  * undiverting named files, by passing a non-numeric argument to
  868.  * undivert ().
  869.  */
  870. static void
  871. m4_undivert (struct obstack *obs, int argc, token_data **argv)
  872. {
  873.   int i, div;
  874.   FILE *fp;
  875.  
  876.   if (argc == 1)
  877.     {
  878.       undivert_all ();
  879.     }
  880.   else
  881.     for (i = 1; i < argc; i++)
  882.       {
  883.     if (sscanf (ARG (i), "%d", &div) == 1)
  884.       insert_diversion (div);
  885.     else if (no_gnu_extensions)
  886.       error ("non-numeric argument to %s", TOKEN_DATA_TEXT (argv[0]));
  887.     else
  888.       {
  889.         fp = path_search (ARG (i));
  890.         if (fp != NULL)
  891.           {
  892.         insert_file (fp);
  893.         fclose (fp);
  894.           }
  895.         else
  896.           error ("can't undivert %s: %s", ARG (i), syserr ());
  897.       }
  898.       }
  899. }
  900.  
  901.  
  902. /*
  903.  * This section contains various macros, which does not fall into any
  904.  * specific group.  These are "dnl", "shift", "changequote" and
  905.  * "changecom".
  906.  */
  907.  
  908. /*
  909.  * Delete all subsequent whitespace from input.  The function
  910.  * skip_line () lives in input.c.
  911.  */
  912. static void
  913. m4_dnl (struct obstack *obs, int argc, token_data **argv)
  914. {
  915.   if (bad_argc (argv[0], argc, 1, 1))
  916.     return;
  917.  
  918.   skip_line ();
  919. }
  920.  
  921. /*
  922.  * Shift all argument one to the left, discarding the first argument.
  923.  * Each output argument is quoted with the current quotes.
  924.  */
  925. static void
  926. m4_shift (struct obstack *obs, int argc, token_data **argv)
  927. {
  928.   dump_args (obs, argc - 1, argv + 1, ",", TRUE);
  929. }
  930.  
  931. /*
  932.  * Change the current quotes.  The function set_quotes () lives in
  933.  * input.c
  934.  */
  935. static void
  936. m4_changequote (struct obstack *obs, int argc, token_data **argv)
  937. {
  938.   if (bad_argc (argv[0], argc, 1, 3))
  939.     return;
  940.  
  941.   set_quotes ((argc >= 2) ? TOKEN_DATA_TEXT (argv[1]) : NULL,
  942.          (argc >= 3) ? TOKEN_DATA_TEXT (argv[2]) : NULL);
  943. }
  944.  
  945. /*
  946.  * Change the current comment delimiters.  The function set_comment ()
  947.  * lives in input.c
  948.  */
  949. static void
  950. m4_changecom (struct obstack *obs, int argc, token_data **argv)
  951. {
  952.   if (bad_argc (argv[0], argc, 1, 3))
  953.     return;
  954.  
  955.   if (argc == 1)
  956.     set_comment ("", "");    /* disable comments */
  957.   else
  958.     set_comment (TOKEN_DATA_TEXT (argv[1]),
  959.         (argc >= 3) ? TOKEN_DATA_TEXT (argv[2]) : NULL);
  960. }
  961.  
  962.  
  963. /*
  964.  * This section contains macros for inclusion of other files --
  965.  * "include" and "sinclude".  This differs from bringing back
  966.  * diversions, in that the input is scanned before being copied to the
  967.  * output.
  968.  */
  969. /*
  970.  * Generic include function.  Include the file given by the first
  971.  * argument, if it exists.  Complain about inaccesible files iff
  972.  * SILENT is FALSE.
  973.  */
  974. static void
  975. include (int argc, token_data **argv, boolean silent)
  976. {
  977.   FILE *fp;
  978.  
  979.   if (bad_argc (argv[0], argc, 2, 2))
  980.     return;
  981.  
  982.   fp = path_search (ARG (1));
  983.   if (fp == NULL)
  984.     {
  985.       if (!silent)
  986.     error ("can't open %s: %s", ARG (1), syserr ());
  987.       return;
  988.     }
  989.  
  990.   push_file (fp, ARG (1));
  991. }
  992.  
  993. /*
  994.  * Include a file, complaining in case of errors.
  995.  */
  996. static void
  997. m4_include (struct obstack *obs, int argc, token_data **argv)
  998. {
  999.   include (argc, argv, FALSE);
  1000. }
  1001.  
  1002. /*
  1003.  * Include a file, ignoring errors.
  1004.  */
  1005. static void
  1006. m4_sinclude (struct obstack *obs, int argc, token_data **argv)
  1007. {
  1008.   include (argc, argv, TRUE);
  1009. }
  1010.  
  1011.  
  1012. /*
  1013.  * More miscellaneous builtins -- "maketemp", "errprint", "__file__" and
  1014.  * "__line__".  The last two are GNU specific.
  1015.  */
  1016.  
  1017. /*
  1018.  * Use the first argument as at template for a temporary file name.
  1019.  */
  1020. static void
  1021. m4_maketemp (struct obstack *obs, int argc, token_data **argv)
  1022. {
  1023.   if (bad_argc (argv[0], argc, 2, 2))
  1024.     return;
  1025.   mktemp (ARG (1));
  1026.   obstack_grow (obs, ARG (1), strlen (ARG (1)));
  1027. }
  1028.  
  1029. /*
  1030.  * Print all arguments on standard error.
  1031.  */
  1032. static void
  1033. m4_errprint (struct obstack *obs, int argc, token_data **argv)
  1034. {
  1035.   dump_args (obs, argc, argv, " ", FALSE);
  1036.   obstack_1grow (obs, '\0');
  1037.   fprintf (stderr, "%s", (char *) obstack_finish (obs));
  1038.   fflush (stderr);
  1039. }
  1040.  
  1041. static void
  1042. m4___file__ (struct obstack *obs, int argc, token_data **argv)
  1043. {
  1044.   if (bad_argc (argv[0], argc, 1, 1))
  1045.     return;
  1046.   obstack_grow (obs, lquote, len_lquote);
  1047.   obstack_grow (obs, current_file, strlen (current_file));
  1048.   obstack_grow (obs, rquote, len_rquote);
  1049. }
  1050.  
  1051. static void
  1052. m4___line__ (struct obstack *obs, int argc, token_data **argv)
  1053. {
  1054.   if (bad_argc (argv[0], argc, 1, 1))
  1055.     return;
  1056.   shipout_int (obs, current_line);
  1057. }
  1058.  
  1059. /*
  1060.  * This section contains various macros for exiting, saving input until
  1061.  * EOF is seen, and tracing macro calls.  That is: "m4exit", "m4wrap",
  1062.  * "traceon" and "traceoff".
  1063.  */
  1064. /*
  1065.  * Exit immediately, with exitcode specified by the first argument, 0 if
  1066.  * no arguments are present.
  1067.  */
  1068. static void
  1069. m4_m4exit (struct obstack *obs, int argc, token_data **argv)
  1070. {
  1071.   int exit_code = 0;
  1072.  
  1073.   if (bad_argc (argv[0], argc, 1, 2))
  1074.     return;
  1075.   if (argc == 2  && !numeric_arg (argv[0], ARG (1), &exit_code))
  1076.     exit_code = 0;
  1077.  
  1078.   exit (exit_code);
  1079. }
  1080.  
  1081. /*
  1082.  * Save the argument text until EOF has been seen, allowing for user
  1083.  * specified cleanup action.  GNU version saves all arguments, the
  1084.  * standard version only the first.
  1085.  */
  1086. static void
  1087. m4_m4wrap (struct obstack *obs, int argc, token_data **argv)
  1088. {
  1089.   if (no_gnu_extensions)
  1090.     {
  1091.       obstack_grow (obs, ARG (1), strlen (ARG (1)));
  1092.     }
  1093.   else
  1094.     dump_args (obs, argc, argv, " ", FALSE);
  1095.   obstack_1grow (obs, '\0');
  1096.   push_wrapup (obstack_finish (obs));
  1097. }
  1098.  
  1099.  
  1100. /*
  1101.  * Enable tracing of all specified macros, or all, if none is specified.
  1102.  * Tracing is disabled by default, when a macro is defined.  This can be
  1103.  * overridden by the "t" debug flag.
  1104.  */
  1105.  
  1106. /*
  1107.  * Set_trace () is used by "traceon" and "traceoff" to enable and disable
  1108.  * tracing of a macro.  It disables tracing if DATA is NULL, otherwise it
  1109.  * enable tracing.
  1110.  */
  1111. static void
  1112. set_trace (symbol *sym, char *data)
  1113. {
  1114.   SYMBOL_TRACED (sym) = (boolean) (data != NULL);
  1115. }
  1116.  
  1117. static void
  1118. m4_traceon (struct obstack *obs, int argc, token_data **argv)
  1119. {
  1120.   symbol *s;
  1121.   int i;
  1122.  
  1123.   if (argc == 1)
  1124.     hack_all_symbols (set_trace, (char *) obs);
  1125.   else
  1126.     for (i = 1; i < argc; i++)
  1127.       {
  1128.     s = lookup_symbol (TOKEN_DATA_TEXT (argv[i]), SYMBOL_LOOKUP);
  1129.     if (s != NULL)
  1130.       set_trace (s, (char *) obs);
  1131.     else
  1132.       error ("Undefined name %s", TOKEN_DATA_TEXT (argv[i]));
  1133.       }
  1134. }
  1135.  
  1136. /*
  1137.  * Disable tracing of all specified macros, or all, if none is
  1138.  * specified.
  1139.  */
  1140. static void
  1141. m4_traceoff (struct obstack *obs, int argc, token_data **argv)
  1142. {
  1143.   symbol *s;
  1144.   int i;
  1145.  
  1146.   if (argc == 1)
  1147.     hack_all_symbols (set_trace, NULL);
  1148.   else
  1149.     for (i = 1; i < argc; i++)
  1150.       {
  1151.     s = lookup_symbol (TOKEN_DATA_TEXT (argv[i]), SYMBOL_LOOKUP);
  1152.     if (s != NULL)
  1153.       set_trace (s, NULL);
  1154.     else
  1155.       error ("Undefined name %s", TOKEN_DATA_TEXT (argv[i]));
  1156.       }
  1157. }
  1158.  
  1159. /*
  1160.  * On-the-fly control of the format of the tracing output.  It takes one
  1161.  * argument, which is a character string like given to the -d option, or
  1162.  * none in which case the debug_level is zeroed.
  1163.  */
  1164. static void
  1165. m4_debugmode (struct obstack *obs, int argc, token_data **argv)
  1166. {
  1167.   int new_debug_level;
  1168.   int change_flag;
  1169.  
  1170.   if (bad_argc (argv[0], argc, 1, 2))
  1171.     return;
  1172.  
  1173.   if (argc == 1)
  1174.     debug_level = 0;
  1175.   else
  1176.     {
  1177.       if (ARG (1)[0] == '+' || ARG (1)[0] == '-')
  1178.     {
  1179.       change_flag = ARG (1)[0];
  1180.       new_debug_level = debug_decode (ARG (1) + 1);
  1181.     }
  1182.       else
  1183.     {
  1184.       change_flag = 0;
  1185.       new_debug_level = debug_decode (ARG (1));
  1186.     }
  1187.  
  1188.       if (new_debug_level < 0)
  1189.     error ("debugmode: bad debug flags: `%s'", ARG (1));
  1190.       else
  1191.     {
  1192.       switch (change_flag)
  1193.         {
  1194.         case 0:
  1195.           debug_level = new_debug_level;
  1196.           break;
  1197.         case '+':
  1198.           debug_level |= new_debug_level;
  1199.           break;
  1200.         case '-':
  1201.           debug_level &= ~new_debug_level;
  1202.           break;
  1203.         }
  1204.     }
  1205.     }
  1206. }
  1207.  
  1208. /*
  1209.  * Specify the destination of the debugging output.  With one argument,
  1210.  * the argument is taken as a file name, with no arguments, revert to
  1211.  * stderr.
  1212.  */
  1213. static void
  1214. m4_debugfile (struct obstack *obs, int argc, token_data **argv)
  1215. {
  1216.   if (bad_argc (argv[0], argc, 1, 2))
  1217.     return;
  1218.  
  1219.   if (argc == 1)
  1220.     debug_set_output (NULL);
  1221.   else if (!debug_set_output (ARG (1)))
  1222.     error ("cannot set error file: %s: %s", ARG (1), syserr ());
  1223. }
  1224.  
  1225.  
  1226. /*
  1227.  * This section contains text processing macros: "len", "index",
  1228.  * "substr", "translit", "format", "regexp" and "patsubst".  The last
  1229.  * three are GNU specific.
  1230.  */
  1231.  
  1232. /*
  1233.  * Expand to the length of the first argument.
  1234.  */
  1235. static void
  1236. m4_len (struct obstack *obs, int argc, token_data **argv)
  1237. {
  1238.   if (bad_argc (argv[0], argc, 2, 2))
  1239.     return;
  1240.   shipout_int (obs, strlen (ARG (1)));
  1241. }
  1242.  
  1243. /*
  1244.  * The macro expands to the first index of the second argument in the
  1245.  * first argument.
  1246.  */
  1247. static void
  1248. m4_index (struct obstack *obs, int argc, token_data **argv)
  1249. {
  1250.   char *cp, *last;
  1251.   int l1, l2, retval;
  1252.  
  1253.   if (bad_argc (argv[0], argc, 3, 3))
  1254.     return;
  1255.  
  1256.   l1 = strlen (ARG (1));
  1257.   l2 = strlen (ARG (2));
  1258.  
  1259.   last = ARG (1) + l1 - l2;
  1260.  
  1261.   for (cp = ARG (1); cp <= last; cp++)
  1262.     {
  1263.       if (strncmp (cp, ARG (2), l2) == 0)
  1264.     break;
  1265.     }
  1266.   retval = (cp <= last) ? cp - ARG (1) : -1;
  1267.  
  1268.   shipout_int (obs, retval);
  1269. }
  1270.  
  1271. /*
  1272.  * The macro "substr" extracts substrings from the first argument,
  1273.  * starting from the index given by the second argument, extending for a
  1274.  * length given by the third argument.  If the third argument is
  1275.  * missing, the substring extends to the end of the first argument.
  1276.  */
  1277. static void
  1278. m4_substr (struct obstack *obs, int argc, token_data **argv)
  1279. {
  1280.   int start, length, avail;
  1281.  
  1282.   if (bad_argc (argv[0], argc, 3, 4))
  1283.     return;
  1284.  
  1285.   length = avail = strlen (ARG (1));
  1286.   if (!numeric_arg (argv[0], ARG (2), &start))
  1287.     return;
  1288.  
  1289.   if (argc == 4 && !numeric_arg (argv[0], ARG (3), &length))
  1290.     return;
  1291.  
  1292.   if (start < 0 || length <= 0 || start >= avail)
  1293.     return;
  1294.  
  1295.   if (start + length > avail)
  1296.     length = avail - start;
  1297.   obstack_grow (obs, ARG (1) + start, length);
  1298. }
  1299.  
  1300. /*
  1301.  * The macro "translit" translates all characters in the first
  1302.  * argument, which are present in the second argument, into the
  1303.  * corresponding character from the third argument.  If the third
  1304.  * argument is shorter than the second, the extra characters in the
  1305.  * second argument, are delete from the first (pueh).
  1306.  *
  1307.  * Ranges are allowed in the second and third argument.  They are
  1308.  * expanded in the following function, and the expanded strings, without
  1309.  * any ranges left, are used to translate the characters of the first
  1310.  * argument.  A single - (dash) can be included in the strings by being
  1311.  * the first or the last character in the string.  If the first
  1312.  * character in a range is after the first in the character set, the
  1313.  * range is made backwards, thus 9-0 is the string 9876543210.
  1314.  */
  1315.  
  1316. static char *
  1317. expand_ranges (char *s, struct obstack *obs)
  1318. {
  1319.   char from;
  1320.   char to;
  1321.  
  1322.   for (from = '\0'; *s != '\0'; from = *s++)
  1323.     {
  1324.       if (*s == '-' && from != '\0')
  1325.     {
  1326.       to = *++s;
  1327.       if (to == '\0')
  1328.         obstack_1grow (obs, '-'); /* trailing dash */
  1329.       else if (from <= to)
  1330.         {
  1331.           while (from++ < to)
  1332.         obstack_1grow (obs, from);
  1333.         }
  1334.       else
  1335.         {
  1336.           while (--from >= to)
  1337.         obstack_1grow (obs, from);
  1338.         }
  1339.     }
  1340.       else
  1341.     obstack_1grow (obs, *s);
  1342.     }
  1343.   obstack_1grow (obs, '\0');
  1344.   return obstack_finish (obs);
  1345. }
  1346.  
  1347. static void
  1348. m4_translit (struct obstack *obs, int argc, token_data **argv)
  1349. {
  1350.   register char *data, *tmp;
  1351.   char *from, *to;
  1352.   int tolen;
  1353.  
  1354.   if (bad_argc (argv[0], argc, 3, 4))
  1355.     return;
  1356.  
  1357.   from = ARG (2);
  1358.   if (index (from, '-') != NULL)
  1359.     {
  1360.       from = expand_ranges (from, obs);
  1361.       if (from == NULL)
  1362.     return;
  1363.     }
  1364.  
  1365.   if (argc == 4)
  1366.     {
  1367.       to = ARG (3);
  1368.       if (index (to, '-') != NULL)
  1369.     {
  1370.       to = expand_ranges (to, obs);
  1371.       if (to == NULL)
  1372.         return;
  1373.     }
  1374.     }
  1375.   else
  1376.     to = "";
  1377.  
  1378.   tolen = strlen (to);
  1379.  
  1380.   for (data = ARG (1); *data; data++)
  1381.     {
  1382.       tmp = (char *) index (from, *data);
  1383.       if (tmp == NULL)
  1384.     {
  1385.       obstack_1grow (obs, *data);
  1386.     }
  1387.       else
  1388.     {
  1389.       if (tmp - from < tolen)
  1390.         obstack_1grow (obs, *(to + (tmp - from)));
  1391.     }
  1392.     }
  1393. }
  1394.  
  1395. /*
  1396.  * Frontend for printf like formatting.  The function format () lives in
  1397.  * the file format.c.
  1398.  */
  1399. static void
  1400. m4_format (struct obstack *obs, int argc, token_data **argv)
  1401. {
  1402.   format (obs, argc - 1, argv + 1);
  1403. }
  1404.  
  1405. /*
  1406.  * Function to perform substitution by regular expressions.  Used by the
  1407.  * builtins regexp and patsubst.  The changed text is place on the
  1408.  * obstack.  The substitution is REPL, with \& substituted by VICTIM (of
  1409.  * length LENGTH), and \N substituted by the text matched by the Nth
  1410.  * parenthesized sub-expression, taken from REGS.
  1411.  */
  1412.  
  1413. static void
  1414. substitute (struct obstack *obs, char *victim, int length,
  1415.         char *repl, struct re_registers *regs)
  1416. {
  1417.   register unsigned int ch;
  1418.  
  1419.   for (;;)
  1420.     {
  1421.       while ((ch = *repl++) != '\\')
  1422.     {
  1423.       if (ch == '\0')
  1424.         return;
  1425.       obstack_1grow (obs, ch);
  1426.     }
  1427.  
  1428.       switch ((ch = *repl++))
  1429.     {
  1430.     case '0': case '1': case '2': case '3': case '4':
  1431.     case '5': case '6': case '7': case '8': case '9':
  1432.       ch -= '0';
  1433.       if (regs->end[ch] > 0)
  1434.         obstack_grow (obs, victim + regs->start[ch],
  1435.               regs->end[ch] - regs->start[ch]);
  1436.       break;
  1437.     case '&':
  1438.       obstack_grow (obs, victim, length);
  1439.       break;
  1440.     default:
  1441.       obstack_1grow (obs, ch);
  1442.       break;
  1443.     }
  1444.     }
  1445. }
  1446.  
  1447. /*
  1448.  * Regular expression version of index.  Given two arguments, expand to
  1449.  * the index of the first match of the second argument (a regexp) in the
  1450.  * first.  Expand to -1 if here is no match.  Given a third argument, is
  1451.  * changes the expansion to this argument,
  1452.  */
  1453.  
  1454. static void
  1455. m4_regexp (struct obstack *obs, int argc, token_data **argv)
  1456. {
  1457.   char *victim;            /* first argument */
  1458.   char *regexp;            /* regular expression */
  1459.   char *repl;            /* replacement string */
  1460.  
  1461.   struct re_pattern_buffer buf;    /* compiled regular expression */
  1462.   struct re_registers regs;    /* for subexpression matches */
  1463.   const char *msg;        /* error message from re_compile_pattern */
  1464.   int startpos;            /* start position of match */
  1465.   int length;            /* length of first argument */
  1466.  
  1467.   if (bad_argc (argv[0], argc, 3, 4))
  1468.     return;
  1469.  
  1470.   victim = TOKEN_DATA_TEXT (argv[1]);
  1471.   regexp = TOKEN_DATA_TEXT (argv[2]);
  1472.   if (argc == 4)
  1473.     repl = TOKEN_DATA_TEXT (argv[3]);
  1474.  
  1475.   buf.buffer = NULL;
  1476.   buf.allocated = 0;
  1477.   buf.fastmap = NULL;
  1478.   buf.translate = NULL;
  1479.   msg = re_compile_pattern (regexp, strlen (regexp), &buf);
  1480.  
  1481.   if (msg != NULL)
  1482.     {
  1483.       error ("bad regular expression: \"%s\": %s", regexp, msg);
  1484.       return;
  1485.     }
  1486.  
  1487.   length = strlen (victim);
  1488.   startpos = re_search (&buf, victim, length, 0, length, ®s);
  1489.   xfree (buf.buffer);
  1490.  
  1491.   if (startpos  == -2)
  1492.     {
  1493.       error ("error matching regular expression \"%s\"", regexp);
  1494.       return;
  1495.     }
  1496.  
  1497.   if (argc == 3)
  1498.     shipout_int (obs, startpos);
  1499.   else if (startpos >= 0)
  1500.     substitute (obs, victim, length, repl, ®s);
  1501.  
  1502.   return;
  1503. }
  1504.  
  1505. /*
  1506.  * Substitute all matches of a regexp occuring in a string.  Each match
  1507.  * of the second argument (a regexp) in the first argument is changed to
  1508.  * the third argument, with \& substituted by the matched text, and \N
  1509.  * substituted by the text matched by the Nth parenthesized
  1510.  * sub-expression.
  1511.  */
  1512.  
  1513. static void
  1514. m4_patsubst (struct obstack *obs, int argc, token_data **argv)
  1515. {
  1516.   char *victim;            /* first argument */
  1517.   char *regexp;            /* regular expression */
  1518.  
  1519.   struct re_pattern_buffer buf;    /* compiled regular expression */
  1520.   struct re_registers regs;    /* for subexpression matches */
  1521.   const char *msg;        /* error message from re_compile_pattern */
  1522.   int matchpos;            /* start position of match */
  1523.   int offset;            /* current match offset */
  1524.   int length;            /* length of first argument */
  1525.  
  1526.   if (bad_argc (argv[0], argc, 3, 4))
  1527.     return;
  1528.  
  1529.   regexp = TOKEN_DATA_TEXT (argv[2]);
  1530.  
  1531.   buf.buffer = NULL;
  1532.   buf.allocated = 0;
  1533.   buf.fastmap = NULL;
  1534.   buf.translate = NULL;
  1535.   msg = re_compile_pattern (regexp, strlen (regexp), &buf);
  1536.  
  1537.   if (msg != NULL)
  1538.     {
  1539.       error ("bad regular expression: \"%s\": %s", regexp, msg);
  1540.       if (buf.buffer != NULL)
  1541.     xfree (buf.buffer);
  1542.       return;
  1543.     }
  1544.  
  1545.   victim = TOKEN_DATA_TEXT (argv[1]);
  1546.   length = strlen (victim);
  1547.  
  1548.   offset = 0;
  1549.   matchpos = 0;
  1550.   while (offset < length)
  1551.     {
  1552.       matchpos = re_search (&buf, victim, length,
  1553.                 offset, length - offset, ®s);
  1554.       if (matchpos < 0)
  1555.     {
  1556.       /*
  1557.        * Match failed -- either error or there is no match in the
  1558.        * rest of the string, in which case the rest of the string
  1559.        * is copied verbatim.
  1560.        */
  1561.       if (matchpos == -2)
  1562.         error ("error matching regular expression \"%s\"", regexp);
  1563.       else if (offset < length)
  1564.         obstack_grow (obs, victim + offset, length - offset);
  1565.       break;
  1566.     }
  1567.       /*
  1568.        * Copy the part of the string that was skipped by re_search ().
  1569.        */
  1570.       if (matchpos > offset)
  1571.     obstack_grow (obs, victim + offset, matchpos - offset);
  1572.  
  1573.       /*
  1574.        * Handle the part of the string that was covered by the match.
  1575.        */
  1576.       substitute (obs, victim, length, ARG (3), ®s);
  1577.  
  1578.       /*
  1579.        * Update the offset to the end of the match.  If the regexp
  1580.        * matched a null string, advance offset one more, to avoid
  1581.        * infinite loops.
  1582.        */
  1583.       offset = regs.end[0];
  1584.       if (regs.start[0] == regs.end[0])
  1585.     obstack_1grow (obs, victim[offset++]);
  1586.     }
  1587.   obstack_1grow (obs, '\0');
  1588.  
  1589.   xfree (buf.buffer);
  1590.   return;
  1591. }
  1592.  
  1593. /*
  1594.  * This function handles all expansion of user defined and predefined
  1595.  * macros.  It is called with an obstack OBS, where the macros expansion
  1596.  * will be placed, as an unfinished object.  SYM points to the macro
  1597.  * definition, giving the expansion text.  ARGC and ARGV are the
  1598.  * arguments, as usual.
  1599.  */
  1600. void
  1601. expand_user_macro (struct obstack *obs, symbol *sym,
  1602.            int argc, token_data **argv)
  1603. {
  1604.   register char *text;
  1605.   int i;
  1606.  
  1607.   for (text = SYMBOL_TEXT (sym); *text != '\0';)
  1608.     {
  1609.       if (*text != '$')
  1610.     {
  1611.       obstack_1grow (obs, *text);
  1612.       text++;
  1613.       continue;
  1614.     }
  1615.       text++;
  1616.       switch (*text)
  1617.     {
  1618.     case '0': case '1': case '2': case '3': case '4':
  1619.     case '5': case '6': case '7': case '8': case '9':
  1620.       if (no_gnu_extensions)
  1621.         {
  1622.           i = *text++ - '0';
  1623.         }
  1624.       else
  1625.         {
  1626.           for (i = 0; isdigit (*text); text++)
  1627.         i = i*10 + (*text - '0');
  1628.         }
  1629.       if (i < argc)
  1630.         obstack_grow (obs, TOKEN_DATA_TEXT (argv[i]),
  1631.               strlen (TOKEN_DATA_TEXT (argv[i])));
  1632.       break;
  1633.  
  1634.     case '#':        /* number of arguments */
  1635.       shipout_int (obs, argc - 1);
  1636.       text++;
  1637.       break;
  1638.  
  1639.     case '*':        /* all arguments */
  1640.     case '@':        /* ... same, but quoted */
  1641.       dump_args (obs, argc, argv, ",", *text == '@');
  1642.       text++;
  1643.       break;
  1644.  
  1645.     default:
  1646.       obstack_1grow (obs, '$');
  1647.       break;
  1648.     }
  1649.     }
  1650. }
  1651.